package cn.tedu.csmall.passport.service.impl;

import cn.tedu.csmall.commons.ex.ServiceException;
import cn.tedu.csmall.commons.pojo.vo.PageData;
import cn.tedu.csmall.commons.util.PageInfoToPageDataConverter;
import cn.tedu.csmall.commons.web.ServiceCode;
import cn.tedu.csmall.passport.mapper.AdminMapper;
import cn.tedu.csmall.passport.mapper.AdminRoleMapper;
import cn.tedu.csmall.passport.pojo.entity.Admin;
import cn.tedu.csmall.passport.pojo.entity.AdminRole;
import cn.tedu.csmall.passport.pojo.param.AdminAddNewParam;
import cn.tedu.csmall.passport.pojo.param.AdminLoginInfoParam;
import cn.tedu.csmall.passport.pojo.param.AdminUpdateInfoParam;
import cn.tedu.csmall.passport.pojo.vo.AdminListItemVO;
import cn.tedu.csmall.passport.pojo.vo.AdminStandardVO;
import cn.tedu.csmall.passport.security.AdminDetails;
import cn.tedu.csmall.passport.service.AdminService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class AdminServiceImpl implements AdminService {
    @Value("${csmall.jwt.secret-key}")
    private String secretKey;
    @Value("${csmall.jwt.duration-in-minute}")
    private Long durationInMinute;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private AdminRoleMapper adminRoleMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public String login(AdminLoginInfoParam adminLoginInfoParam) {
        log.debug("开始处理【管理员登陆】业务，参数：{}", adminLoginInfoParam);

        Authentication authentication = new UsernamePasswordAuthenticationToken(
                adminLoginInfoParam.getUsername(),
                adminLoginInfoParam.getPassword()
        );

        Authentication authenticationResult = authenticationManager.authenticate(authentication);
        log.debug("处理【管理员登陆】业务完毕！认证结果：{}",authenticationResult);

        AdminDetails adminDetails = (AdminDetails) authenticationResult.getPrincipal();

        //jwt
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", adminDetails.getId());
        claims.put("username", adminDetails.getUsername());
        claims.put("authorities", JSON.toJSONString(adminDetails.getAuthorities()));

        String jwt = Jwts.builder()
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")

                .setClaims(claims)

                .setExpiration(new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000))
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();

        System.out.println(jwt);
        return jwt;
    }

    /*
    * 添加管理员
    * */
    @Override
    public void addNew(AdminAddNewParam adminAddNewParam) {
        //从数据库中查询是否有相同的username
        log.debug("开始处理【添加管理员】业务：从数据库中查询是否有相同的username:");
        QueryWrapper<Admin> addNewQW = new QueryWrapper();
        addNewQW.eq("username", adminAddNewParam.getUsername());
        Integer num = adminMapper.selectCount(addNewQW);

        log.debug("查询到数据库中和其同名的数量为：{}", num);
        if (num == 1) {
            String message = "管理员表中有数据与其同名，添加失败！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        //向管理员数据库中添加数据
        log.debug("检测通过，用户输入的数据，{}",adminAddNewParam);
        Admin admin = new Admin();
        BeanUtils.copyProperties(adminAddNewParam, admin);
        String rawPassword = admin.getPassword();
        String encodedPassword = passwordEncoder.encode(rawPassword);
        admin.setPassword(encodedPassword)
                .setGmtCreate(LocalDateTime.now())
                .setGmtModified(LocalDateTime.now());

        log.debug("向管理员数据库中添加的数据为：{}", admin);
        adminMapper.insert(admin);
        log.debug("添加完成后的admin对象：{}",admin);
        log.debug("添加成功！");

        //向管理员角色数据库中添加对应关系
        log.debug("向管理员角色数据库中添加对应关系");
        Long[] roleIds = adminAddNewParam.getRoleIds();
        Arrays.sort(roleIds);
        AdminRole[] adminRoles = new AdminRole[roleIds.length];
        for (int i = 0; i < roleIds.length; i++) {
            AdminRole adminRole = new AdminRole();
            adminRole.setAdminId(admin.getId());
            adminRole.setRoleId(roleIds[i]);
            adminRole.setGmtCreate(LocalDateTime.now());
            adminRole.setGmtModified(LocalDateTime.now());
            adminRoles[i] = adminRole;
        }
        adminRoleMapper.insertBatch(adminRoles);
        log.debug("添加完成！");
    }

    @Override
    public void delete(Long id) {
        log.debug("开始处理【根据id删除管理员】业务，id：{}", id);
        //判断管理员中有无此id
        log.debug("判断管理员中有无此id!");
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        Integer integer = adminMapper.selectCount(queryWrapper);
        log.debug("查询结果为：{}", integer);
        if (integer == 0) {
            String message = "管理员中无此id，删除失败！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        //判断管理员和角色关联表中有无和此id关联的信息
        log.debug("判断管理员和角色关联表中有无和此id关联的信息");
        QueryWrapper<AdminRole> adminRoleQueryWrapper = new QueryWrapper<>();
        adminRoleQueryWrapper.eq("admin_id", id);
        Integer integer1 = adminRoleMapper.selectCount(adminRoleQueryWrapper);
        log.debug("查询结果为：{}", integer1);
        if (integer1 != 0) {
            log.debug("开始查询和该管理员关联的角色id！");
            int i = adminRoleMapper.deleteByAdminId(id);
            if (i != integer1) {
                String message = "删除失败，服务器忙，请稍后再试！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_DELETE, message);
            }
        }

        //开始删除
        log.debug("删除关联完成，开始删除！");
        int delete = adminMapper.deleteById(id);
        if (delete == 0) {
            String message = "删除失败，服务器忙，请稍后再试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }
        log.debug("删除成功！");
    }

    @Override
    public void updateInfoById(Long id, AdminUpdateInfoParam adminUpdateInfoParam) {
        log.debug("开始处理【根据id修改管理员信息】业务");
        //判断管理员中是否有此id
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        Integer integer = adminMapper.selectCount(queryWrapper);
        if (integer == 0) {
            String message = "修改失败，判断管理员中无此id！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        //开始判断手机号和其他管理员是否有冲突
        log.debug("开始判断手机号和其他管理员是否有冲突");
        String phone = adminUpdateInfoParam.getPhone();
        QueryWrapper<Admin> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("phone", phone).ne("id", id);
        Integer integer1 = adminMapper.selectCount(queryWrapper1);
        if (integer1 != 0) {
            String message = "修改电话号失败，与其他管理员冲突！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        //开始判断邮箱和其他管理员是否有冲突
        log.debug("开始判断邮箱和其他管理员是否有冲突");
        String email = adminUpdateInfoParam.getEmail();
        QueryWrapper<Admin> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("email", email).ne("id", id);
        Integer integer2 = adminMapper.selectCount(queryWrapper2);
        if (integer2 != 0) {
            String message = "修改邮箱失败，与其他管理员冲突！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        //开始修改管理员表信息
        log.debug("检查通过，开始修改管理员表信息");
        Admin admin = new Admin();
        BeanUtils.copyProperties(adminUpdateInfoParam, admin);
        admin.setGmtModified(LocalDateTime.now());
        admin.setId(id);
        int i = adminMapper.updateById(admin);
        if (i == 0) {
            String message = "修改管理员信息失败，系统繁忙，请稍后再试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
        log.debug("修改管理员表信息成功！");

        //开始修改管理员和角色关联表的信息
//        log.debug("开始修改管理员和角色关联表的信息");
//        List<Long> listNew = adminUpdateInfoParam.getRoleIds();  //4.5
//        log.debug("查询该管理员原来的角色！");
//        List<Long> listOld = adminRoleMapper.selectRoleIdByAdminId(id);  //3.4
//        List<Long> list = new ArrayList<>();
//        for (Long l : listNew) {
//            list.add(l);
//        }
//        list.removeAll(listOld);
//        log.debug("需要添加的角色id为：{}", list);
//        System.out.println(listNew.toString());
//        listOld.removeAll(listNew);
//        log.debug("需要删除的角色id为：{}", listOld);
//
//        //在管理员和角色表中添加新角色list
//        log.debug("在管理员和角色表中添加新角色list");
//        List<AdminRole> adminRoleList = new ArrayList<>();
//        for (Long l : list) {
//            AdminRole adminRole = new AdminRole();
//            adminRole.setAdminId(id)
//                    .setRoleId(l)
//                    .setGmtCreate(LocalDateTime.now())
//                    .setGmtModified(LocalDateTime.now());
//            adminRoleList.add(adminRole);
//        }
//        int i1 = adminRoleMapper.insertListRoleIds(adminRoleList);
//        if (i1 != list.size()) {
//            String message = "添加管理员和角色id失败，服务器繁忙，请稍后再试！";
//            log.warn(message);
//            throw new ServiceException(ServiceCode.ERR_INSERT, message);
//        }
//
//        //在管理员和角色表中删除旧角色listOld
//        log.debug("在管理员和角色表中删除旧角色listOld");
////        List<AdminRole> adminRoleList1 = new ArrayList<>();
////        for (Long l : listOld) {
////            AdminRole adminRole = new AdminRole();
////            adminRole.setRoleId(l);
////            adminRoleList1.add(adminRole);
////        }
//        int i2 = adminRoleMapper.deleteByAdminIdAndRoleIds(id,listOld);
//        if (i2 != listOld.size()) {
//            String message = "删除管理员和角色id失败，服务器繁忙，请稍后再试！";
//            log.warn(message);
//            throw new ServiceException(ServiceCode.ERR_INSERT, message);
//        }

        log.debug("修改管理员信息成功！");
    }

    @Override
    public void updatePasswordById(Long id, String password) {
        log.debug("开始处理【根据id修改管理员密码】业务");
        //判断管理员中是否有此id
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        Integer integer = adminMapper.selectCount(queryWrapper);
        if (integer == 0) {
            String message = "修改密码失败，判断管理员中无此id！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        //开始修改密码
        log.debug("检查通过！开始修改密码！");
        Admin admin = new Admin();
        admin.setId(id)
                .setPassword(passwordEncoder.encode(password));
        int i = adminMapper.updateById(admin);
        if (i == 0) {
            String message = "修改密码失败，服务器忙，请稍后再试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
        log.debug("修改成功!");
    }

    //查询列表（分页）
    @Override
    public PageData<AdminListItemVO> list(Integer pageNum) {
        Integer pageSize = 5;
        return list(pageNum, pageSize);
    }

    //查询列表（分页）
    @Override
    public PageData<AdminListItemVO> list(Integer pageNum,Integer pageSize) {
        log.debug("开始处理【查询管理员列表功能】！页数：{}，每页最大数量：{}", pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<AdminListItemVO> list = adminMapper.list();
        PageInfo<AdminListItemVO> pageInfo = new PageInfo<>(list);
        PageData<AdminListItemVO> pageData = PageInfoToPageDataConverter.convert(pageInfo);
        log.debug("查询完毕！返回数据");
        return pageData;
    }

    //根据ID查询管理员
    @Override
    public AdminStandardVO getStandardById(Long id) {
        log.debug("开始根据id查询相册：");
        AdminStandardVO queryResult = adminMapper.getStandard(id);
        if (queryResult == null) {
            String message = "不存在该id的管理员！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        return queryResult;
    }
}
